package com.yning.coroutines.demo

import com.yning.coroutines.Log
import kotlinx.coroutines.*

/**
 * 协程启动模式有四种
 * CoroutineStart.DEFAULT // 默认 立即执行协程体
 * CoroutineStart.LAZY // 只有在需要的情况下运行
 * CoroutineStart.ATOMIC // 立即执行协程体，但在开始运行之前无法取消
 * CoroutineStart.UNDISPATCHED 立即在当前线程执行协程体，直到第一个 suspend 调用
 */

@ExperimentalCoroutinesApi
suspend fun main() {
    // 默认启动模式--CoroutineStar.Default
    //runByDefault()
    //runByLazy()
    //runCancelByDefault()
    //runCancelByAtomic()
    runByUnDispatched()
}

// 协程启动模式--默认
suspend fun runByDefault(){
    Log.d("1")
    val job = GlobalScope.launch {
        Log.d("2")
    }
    Log.d("3")
    job.join() // 对于Join，需要等协程结束
    Log.d("4")
}

suspend fun runByLazy(){
    Log.d("1")
    //
    val job = GlobalScope.launch(start = CoroutineStart.LAZY) {
        Log.d("2")
    }
    Log.d("3")
    //job.start()
    job.join() // 对于Join，需要等协程结束
    Log.d("4")
}

/**
 *  通过默认的启动方式启动协程，之后在代码中取消，那么会出现结果：
 *  1：协程开始执行时，尚未被cancel，协程正常执行，打印log(2)
 *  2：协程尚未开始，即被cancel，协程被取消
 */
suspend fun runCancelByDefault(){
    Log.d("1")
    val job = GlobalScope.launch {
        Log.d("2")
    }
    Log.d("3")
    job.cancel() // 取消协程
    Log.d("4")
}

/**
 *  对于启动模式为CoroutineStart.ATOMIC
 *  可以先简单理解为：协程一定会被启动，而不被取消
 *  在遇到第一个挂起函数时，会被取消
 */
@ExperimentalCoroutinesApi
suspend fun runCancelByAtomic(){
    Log.d("1")
    val job = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
        Log.d("2")
        // delay定义为suspend函数，挂起函数，delay可被cancel，log(5)不执行
        delay(1000)
        Log.d("5")
    }
    Log.d("3")
    job.cancel() // 取消协程
    Log.d("4")
}

/**
 *  对于启动模式CoroutineStart.UNDISPATCHED
 *  协程会立即执行，调度执行和立即执行的区别在于log(2)一定在log(4)之前
 *  顺序，log(1)->log(2)->log(4)->log(3)->log(5)
 */
@ExperimentalCoroutinesApi
suspend fun runByUnDispatched(){
    Log.d("1")
    val job = GlobalScope.launch(start = CoroutineStart.UNDISPATCHED) {
        Log.d("2")
        // delay定义为suspend函数，挂起函数，delay可被cancel，log(5)不执行
        delay(100)
        Log.d("3")
    }
    Log.d("4")
    job.join()
    Log.d("5")
}